#
#  PodPlaylist.py
#
# This work is released under the GNU GPL, version 2 or later.
#
from Playlist import *
from PodTrack import *
import os, time,md5
from utils import *
from ipod import *

##class PodMasterPlaylist(Playlist):
##	def __init__(self,library):
##		Playlist.__init__(self,library)
##		self.master = True
##		self.name = unikode(i18n("Library"))
##
##	#def setDevice(self,atom):
##	#	self.atom = atom
##		
##	def setName(self,name):
##		pass

MAC_EPOCH_OFFSET  = 2082844800L

class PodPlaylist(Playlist):
	def __init__(self,library,master):
		Playlist.__init__(self,library)
		self.master = master
		self.playlist = None
	
	def markDirty(self):
		self.library().markDirty()

	def fromPodPlaylist(self,playlist):
		#print "PodPlaylist reading",playlist
		self.playlist = playlist
		self.name = unikode(playlist.name)
		#print "PodPlaylist.fromPodPlaylist() got name",playlist.name
		self.playlistID = playlist.id
		incomingTracks = {}
		#
		# add tracks I don't know about
		#
		for trackItem in playlist.trackItems:
			#print "LPodPlaylist.fromPodPlaylist: track",track
			try:
				id = trackItem.id
				if not self.containsTrackID(id):
					#print "adding id",id
					self.addTrackID(id)
				incomingTracks[id] = 1
			except: track = None
		#
		# remove tracks no longer there
		#
		for trackID in self.getTrackIDs():
			try: incomingTracks[trackID]
			except:
				#print "removing",trackID
				self.removeTrackID(trackID)
	
	def setName(self,name):
		#print "PodPlaylist.setName: setting name to",name
		self.name = unikode(name)
		self.playlist.name = self.name
		#print self.playlist,self.playlist.name
		self.library().markDirty()
	
	#
	#
	#def uploadTrack(self,track,callback=None, data = None):
	#	trackID = PodMasterPlaylist.uploadTrack(self,track,callback,data)
	#	plt = self.playlist.addTrack(trackID)
	#	return trackID
		
	def addPodTrackIDs(self,trackIDs):
		for trackID in trackIDs:
			self.addPodTrackID(trackID)
	
	def addPodTrackID(self,trackID):
		if not self.containsTrackID(trackID):
			#print "PodPlaylist: adding trackID",trackID
			#self.addTrackID(trackID)
			#plt = self.playlist.addTrackID(trackID)
			trackItem = IPodTrackItem(self.playlist)
			trackItem.id = trackID
			self.markDirty()

##	def removePodTrackIDs(self,trackIDs):
##		needsUpdate = False
##		for trackID in trackIDs:
##			if self.containsTrackID(trackID):
##				#print "PodPlaylist: removing trackID",trackID
##				self.removeTrackID(trackID)
##				index = self.library().indexOfTrackID(trackID)
##				self.playlist.removeTrackWithIndex(index)
##				self.markDirty()

	def removePodTrackIDs(self,trackIDs):
		#print 'removing trackIDs',trackIDs
		for trackID in trackIDs:
			self.removePodTrackID(trackID)
	
	def removePodTrackID(self,trackID):
		if self.containsTrackID(trackID):
			self.removeTrackID(trackID)
			if self.master:
				self.playlist.removeTrackItemForID(trackID)
				self.library().removePodTrackIDFromAllPlaylists(trackID)
				self.library().killTrackID(trackID)
			else:
				self.playlist.removeTrackItemForID(trackID)
			self.markDirty()

	def uploadTrack(self,track,callback = None,data = None):
		t = self.library().findTrackLike(track)
		if t:
			print "PodPlaylist.uploadTrack() - I already have this track!",t.trackID
			self.addPodTrackID(t.trackID)
			return t.trackID
		else:
			if not os.path.exists(track.location): # make this this file even exists
				print "PodPlaylist.uploadTrack: source file missing"
				return 0
			if self.library().diskFull():
				print "PodPlaylist.uploadTrack: iPod disk full"
				return -1
			localFileName = self.manufactureLocalPathFor(track)
			fullPath = os.path.join(self.library().basePath,localFileName)
			#print "PodPlaylist::uploadTrack uploading from",[track.location]
			if 1:
				#
				# now we have to update the database - tricky!
				#
				t = IPodTrack(self.library().ipod)
				#print "copying"
				#copyFile(track.location,fullPath,callback,data,track.size)  # copy the file
				t.upload(unikode(track.location).encode("latin-1"),callback,data)
				#print "created track",t,t.trackID
				if track.kind.startswith('MPEG-4'):
					t.vbr = 0
					#t.unk14 = 0x10000033
				else:
					try:
						self.format.index('VBR')
						t.vbr = 0x101
					except:
						t.vbr = 0x100
				
				if track.rating: t.rating = track.rating*20
				if track.size: t.size = track.size
				if track.totalTime: t.duration = track.totalTime
				if track.trackNum: t.trackNumber = track.trackNum
				if track.trackCount: t.trackCount = track.trackCount
				if track.discNum: t.discNumber = track.discNum
				if track.discCount: t.discCount = track.discCount
				if track.bitRate:  t.bitRate = track.bitRate/1000
				if track.sampleRate:
					t.sampleRate = track.sampleRate
					#t.sampleRate2 = float(track.sampleRate)
				t.addedTime = long(time.time()) #+MAC_EPOCH_OFFSET
				t.lastModifiedTime = t.addedTime
				t.dbidlo = t.addedTime # manufacture some junk
				t.dbidhi = t.addedTime
				t.dbid2lo = t.addedTime
				t.dbid2hi = t.addedTime
				t.title = unikode(track.title)
				if track.album: t.album = unikode(track.album)
				if track.artist: t.artist = unikode(track.artist)
				if track.genre: t.genre = unikode(track.genre)
				#if track.location: t.addStringOfType(mh_atom.LOCATION).setString(self.playerLocationOf(localFileName))
				if track.comment: t.comment = unikode(track.comment)
				if track.composer: t.composer = unikode(track.composer)
				if track.grouping: t.grouping = unikode(track.grouping)
				t.fileType = unikode(track.kind)
				self.addPodTrackID(t.id)
				if not self.master: # force track into master list
					self.library().mainPlaylist.addPodTrackID(t.id)
				#print "done with adding stuff"
				self.markDirty()
				return t.id
			else:
				print "problem copying file from",track.location,"to",fullPath
				return 0

	def playerLocationOf(self,path):
		#print "converting",path
		path = ':'.join(path.split('/'))
		path = ':'+path
		#print "result = ",path
		return path

	def countHashDirectories(self):
		basePath = os.path.join(self.library().basePath,"iPod_Control","Music")
		files = os.listdir(basePath)
		count = 0
		for file in files:
			if file[0] in ['f','F']:
				index = int(file[1:])
				if index>count: count = index
		if count==0: return 20
		return count+1

	def smash(self,fileName):
		result = ""
		for ch in fileName:
			if ch.isalnum() or ch==' ':
				result = result+ch
		return result

	#
	# here we manufacture a unique filename for the file on the iPod
	# 
	def manufactureLocalPathFor(self,track):
		hash = self.countHashDirectories()
		basePath = os.path.join("iPod_Control","Music")
		#(root,fileName) = os.path.split(track.location)
		#if len(fileName)>70: # name too long!
		fileName = crushToAscii.crush(track.title)
		sum = 0
		for c in fileName: sum = sum+ord(c)
		sum = sum%hash # XXX DSM should vary per model
		rootPath = os.path.join(basePath,("F%02d" % sum))
		m = md5.new()
		m.update(fileName)
		rootName = m.hexdigest()[:18]
		index = 1
		fileName = rootName
		(root,ext) = os.path.splitext(track.location)
		while 1: # resolve collisions
			fullPath = os.path.join(rootPath,fileName+ext)
			if not os.path.exists(fullPath): break
			fileName = "%s%d" % (rootName,index)
		return fullPath
		
	def uploadTracks(self,tracks,callback = None,data = None):
		#print "PodMasterPlaylist: upload tracks",tracks
		for track in tracks:
			#if track.kind == 'MP3 audio file':
			trackID = self.uploadTrack(track,callback,data)

	def downloadTrack(self,track,callback = None, data = None):
		track.download(callback,data)
	
	def downloadTrackID(self,trackID,callback = None, data = None):
		track = self.trackWithTrackID(trackID)
		if track:
			self.downloadTrack(track,callback,data)
		

	#
	# creates a dictionary of tracks keyed with title/artist/album string
	#
	def hashList(self):
		result = {}
		for track in self.getTracks():
			result[track.hashKey()] = track
		return result

	#
	# compare this playlist with another playlist to see what we need to add or remove to make it the same
	#
	def getSyncInfoWith(self,playlist):
		tracksOnPlayerNotInLsongs = self.hashList()
		tracksInLsongsNotOnPlayer = {}
		removedTracks = {}
		
		for track in playlist.getTracks():
			if track.kind.startswith('MPEG'): #,'WAV audio file']:
				key = track.hashKey()
				if tracksOnPlayerNotInLsongs.has_key(key):
					#print "removing",key
					removedTracks[key] = track
					del tracksOnPlayerNotInLsongs[key]
				else:
					#print "adding",key
					if not tracksInLsongsNotOnPlayer.has_key(key) and not removedTracks.has_key(key): # handle dups
						tracksInLsongsNotOnPlayer[key] = track
					#else: print "duplicate!"
		return (tracksInLsongsNotOnPlayer,tracksOnPlayerNotInLsongs)
